package tech.yunjing.train.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import tech.yunjing.train.common.Constants;
import tech.yunjing.train.dao.CodeDao;
import tech.yunjing.train.dao.UserInfoDao;
import tech.yunjing.train.entity.UserInfo;
import tech.yunjing.train.entity.VerificationCode;
import tech.yunjing.train.service.RegisterService;
import tech.yunjing.train.service.exception.*;
import tech.yunjing.train.util.Utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * purpose：实现注册信息逻辑的类
 * Created by 吕祥 on 2017/6/8.
 */
@Service
public class RegisterServiceImpl implements RegisterService, Constants {
    //注入的UserInfoDao
    @Autowired
    UserInfoDao userInfoDao;

    //注入的CodeDao
    @Autowired
    CodeDao codeDao;

    /**
     * 校验手机账号是否已注册
     * @param userAccount 用户信息
     * @return 用户信息
     */
    @Override
    public boolean verifyUserAccount(String userAccount) {
        //判断账号为空
        if(userAccount == null || userAccount.trim().isEmpty()) {
            throw new VerifyUserAccountException("账号不能为空~！");
        }

        //正则模型 校验手机账号规范
        String userAccountModel ="^[1][3,4,5,7,8][0-9]{9}$";
        //判断格式是否正确
        if(userAccount.matches(userAccountModel)) {
            //找到所有用户对象
            UserInfo userInfo = new UserInfo();
            List<UserInfo> allUser = userInfoDao.findAllUserInfo(userInfo);
            //遍历所有对象
            for(UserInfo user : allUser) {
                if(user.getUserAccount().equals(userAccount)) {
                    throw new VerifyUserAccountException("用户已经存在~！");
                }
            }
        } else {
            throw new VerifyUserAccountException("账号格式错误~！");
        }

        return false;
    }


    /**
     * 模拟发送短信验证码(发送到前台，正常是不能返回到前台的)
     * @return 生成的验证码
     */
    @Override
    public String sendVerificationCode() {

        VerificationCode verificationCode = new VerificationCode();
        //接收生成随机验证码
        String code = Utils.getRandomCode();
        //设置生成的验证码保存到对象中
        verificationCode.setVerificationCode(code);
        //验证码使用状态设置为 没有使用
        verificationCode.setStatus(VERIFICATION_CODE_NORMAL);
        //保存验证码到 MongoDb

        //让用户id自增
        List<VerificationCode> allCode = codeDao.findAllVerificationCode(verificationCode);
        verificationCode.setId(allCode.size()+1);

        codeDao.saveCode(verificationCode);
        return code;
    }

    /**
     * 校验注册信息并保存
     * @param userAccount 用户账号
     * @param userPassword 用户密码
     * @param sex 性别
     * @param idNumber 身份证号
     * @param site 住址
     * @param verificationCode 验证码
     * @return 注册的用户信息
     */
    @Override
    public UserInfo verifyUserInfoAndSave(String userAccount, String userPassword, String sex,
                                          String idNumber, String site, String verificationCode) {

        UserInfo userInfo = new UserInfo();
        //判断手机账号是否存在
        if (this.verifyUserAccount(userAccount) == false) {
            //保存手机账号
            userInfo.setUserAccount(userAccount);
        }
        if (userPassword == null || userPassword.trim().isEmpty()) {
            throw new VerifyUserPasswordException("请输入密码~！");
        }

        //正则模型 6-16位
        String userPasswordModel = "^\\s*[^\\s\u4e00-\u9fa5]{6,16}\\s*$";
        //判断密码格式
        if (userPassword.matches(userPasswordModel)) {
            //格式正确保存生成摘要后的密码
            userInfo.setUserPassword(Utils.md5salt(userPassword));
        } else {
            //如果没通过正则判断则抛出异常
            throw new VerifyUserPasswordException("密码格式或长度错误~！");
        }

        //设置创建用户时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
        String creationTime = simpleDateFormat.format(date);
        userInfo.setCreationTime(creationTime);

        //删除时间设置为空
        userInfo.setDeleteTime(null);
        //性别不为空并通过正则判断 添加性别成功
        if (sex == null || sex.trim().isEmpty()) {
            throw new VerifySexException("性别不能为空~！");
        }
        if (sex.equals("男") || sex.equals("女")) {
            userInfo.setSex(sex);
        } else {
            throw new VerifySexException("性别填写错误~！");
        }

        //判断身份证是空
        if (idNumber == null || idNumber.trim().isEmpty()) {
                throw new VerifyIdNumberException("身份证填写错误~！");
        }
        //定义判别用户身份证号的正则表达式 是18位
        String inNuberRegular = "/^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$|^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$";
        if (idNumber.matches(inNuberRegular)) {
            userInfo.setIdNumber(idNumber);
        }

        //判断住址
        if (site == null || site.trim().isEmpty()) {
            throw new VerifySiteException("地址不能为空~！");
        }
        //住址正则 表示由汉字、数字、字母构成
        String siteRegular = "^[\\dA-Za-z\\u4E00-\\u9FA5]+$";
        if (site.matches(siteRegular)) {
            userInfo.setSite(site);
        } else {
            throw new VerifySiteException("地址格式错误~！");
        }

        //设置用户状态
        userInfo.setStatus(DEL_USERLOGIC_NORMAL);

        //判断验证码
        if (verificationCode == null || verificationCode.trim().isEmpty()) {
            throw new VerifyCodeException("验证码不能为空~！");
        }
        //根据字段查找验证码
        Query queryCode = new Query(Criteria.where("verificationCode").is(verificationCode));
        if (queryCode == null) {
            throw new VerifyCodeException("请输入验证码~！");
        }
        //接收查到验证码
        VerificationCode codeOne = codeDao.findCodeOne(queryCode);
        if (codeOne == null) {
            throw new VerifyCodeException("验证码不存在~！");
        }
        //判断是否存在
        if (codeDao.isVerificationCodeExists(verificationCode) || codeOne.getStatus() == VERIFICATION_CODE_DELETE) {
            throw new VerifyCodeException("验证码失效~！");
        }
        //和输入的验证码对比 可用则修改状态
        if (codeOne.getVerificationCode().equals(verificationCode) && codeOne.getStatus() == VERIFICATION_CODE_NORMAL) {
            Update updateCode = new Update();
            //利用 update 对象修改用户状态
            updateCode.set("status", VERIFICATION_CODE_DELETE);
            //执行修改
            codeDao.updateVerificationCodeStatus(queryCode, updateCode);
        }

        //让用户id自增
        List<UserInfo> allUser = userInfoDao.findAllUserInfo(userInfo);
        userInfo.setId(allUser.size()+1);

        userInfoDao.saveUserInfo(userInfo);

        return userInfo;
    }

    /**
     * 根据账号修改密码
     * @param userAccount 账号
     * @param userPassword 密码
     * @return 修改是否成功提示
     */
    @Override
    public String updateOneUserAccount(String userAccount, String userPassword, String updatePassword) {

        if((userAccount == null || userAccount.trim().isEmpty()) || (userPassword == null || userPassword.trim().isEmpty())) {
            throw new UserInfoUpdateException("请输入账号或密码~！");
        }
        if (updatePassword.trim().isEmpty()) {
            throw new UserInfoUpdateException("请输入修改密码~！");
        }
        String MdUserPassword = Utils.md5salt(userPassword);
        //查询输入账号
        Query queryUserInfo = new Query(Criteria.where("userAccount").is(userAccount).and("userPassword").is(MdUserPassword));

        //根据查询出的账号找实体对象
        UserInfo gainUser = userInfoDao.findOneUserInfo(queryUserInfo);
        if (gainUser == null) {
            throw new UserInfoUpdateException("账号或密码错误~！");
        }
        if (gainUser.getStatus() == DEL_USERLOGIC_NORMAL) {
            Update update = new Update();
            //修改密码
            update.set("userPassword", Utils.md5salt(updatePassword));
            userInfoDao.updateOneUserAccount(queryUserInfo, update);
            return "修改密码成功";
        }
        return "修改失败！";
    }

    /**
     * 逻辑删除用户
     * @param userAccount 用户账号
     * @return 是否成功提醒
     */
    @Override
    public String removeOneUserInfo(String userAccount, String userPassword) {

        if((userAccount == null || userAccount.trim().isEmpty()) || (userPassword == null || userPassword.trim().isEmpty())) {
            throw new UserInfoUpdateException("请输入账号或密码~！");
        }

        String MdUserPassword = Utils.md5salt(userPassword);
        //查询输入账号
        Query queryUserInfo = new Query(Criteria.where("userAccount").is(userAccount).and("userPassword").is(MdUserPassword));
        if (queryUserInfo == null) {
            throw new UserInfoDeleteException("请输入账号或密码");
        }
        UserInfo gainUser = userInfoDao.findOneUserInfo(queryUserInfo);
        if (gainUser == null) {
            throw new UserInfoDeleteException("账号或密码错误~！");
        }
        if (gainUser.getStatus() == DEL_USERLOGIC_DELETE) {
            throw new UserInfoDeleteException("账户不存在~！");
        }

        //修改用户状态 (逻辑删除)
        Update updateUserStatus = new Update();
        //修改状态为删除
        updateUserStatus.set("status", DEL_USERLOGIC_DELETE);
        //修改删除时间
        //设置创建用户时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
        String deleteTime = simpleDateFormat.format(date);
        updateUserStatus.set("deleteTime", deleteTime);
        userInfoDao.removeOneUserInfo(queryUserInfo, updateUserStatus);

        return "删除成功";
    }


    /**
     * 根据userAccount查询一条数据
     * @param userAccount 用户账号
     * @return 用户信息对象
     */
    @Override
    public UserInfo findByUserAccount(String userAccount, String userPassword) {

        if((userAccount == null || userAccount.trim().isEmpty()) || (userPassword == null || userPassword.trim().isEmpty())) {
            throw new UserInfoUpdateException("请输入账号或密码~！");
        }

        String MdUserPassword = Utils.md5salt(userPassword);
        //查询输入账号
        Query queryUserInfo = new Query(Criteria.where("userAccount").is(userAccount).and("userPassword").is(MdUserPassword));

        //根据查询出的账号找实体对象
        UserInfo gainUser = userInfoDao.findOneUserInfo(queryUserInfo);

        if (gainUser == null) {
            throw new UserInfoUpdateException("账号或密码错误~！@！");
        }
        System.out.println(gainUser);
        return gainUser;
    }

}
